package com.hq.instantiation;


import java.util.concurrent.FutureTask;

/**
 * 创建线程的3种方式 extends Thread   implements Runnable（软ā了波）  implements Callable(卡了波) FutrueTask。
 *
 * @author hq
 * <p>
 * 创建线程的总结：
 * 1、推荐使用后2种，实现接口的方式，这样可以避免单继承的局限性。
 * 2、接口更合适多个相同程序代码的线程去共享一个资源（不是很能理解）。
 * <p>
 * 讨论实现 Runnable 和 Callable 比较？
 * 1、Runnable 和 Callable 都需要通过Thread,start()启动线程。
 * 2、Runnable 不能抛异常  Callable可以抛异常。
 * 3、Callable 通过 FutureTask(塔斯可).get()获取返回值 Runnable没有返回值。
 * 4、Callable 可以通过 FutureTask.cancel方法进行打断等其他方法进行监控 Runnable不能。
 * <p>
 * 注意点：
 * Callable 在执行get方法的时候  会组合主线程 直到get到结果为止，这里会影响高并发。
 * 提问：
 * java main方法启动的同时启动的线程是？  main 和 垃圾回收。
 */
/**
 * 创建线程的总结：
 *  1、推荐使用后2种，实现接口的方式，这样可以避免单继承的局限性。
 *  2、接口更合适多个相同程序代码的线程去共享一个资源（不是很能理解）。
 *
 * 讨论实现 Runnable 和 Callable 比较？
 *  1、Runnable 和 Callable 都需要通过Thread,start()启动线程。
 *  2、Runnable 不能抛异常  Callable可以抛异常。
 *  3、Callable 通过 FutureTask(塔斯可).get()获取返回值 Runnable没有返回值。
 *  4、Callable 可以通过 FutureTask.cancel方法进行打断等其他方法进行监控 Runnable不能。
 *
 *  注意点：
 *      Callable 在执行get方法的时候  会组合主线程 直到get到结果为止，这里会影响高并发。
 *  提问：
 *      java main方法启动的同时启动的线程是？  main 和 垃圾回收。
 */

/**
 * 线程的生命周期
 * 1、创建阶段
 *      通过new Thread() 就到了这状态  jvm就会分配内存，初始化成员变量。
 * 2、就绪阶段
 *      调用start后进入该状态 jvm会为线程，分配程序计数器和方法栈 等待线程调度器调用。
 * 3、运行阶段
 *      获取到cpu资源 执行run方法。
 * 4、阻塞阶段
 *      1、调用sleep()方法。
 *      2、获取一个带有同步锁的资源时，锁已经其他线程占用的情况下。
 *      3、调用一个阻塞式 io方法的时候。
 *      4、方法中有等待通知的方法时。
 * 5、死亡阶段
 *      1、线程正常执行完run || call方法后。
 *      2、在执行过程中 抛出一个未被捕获的Exception Error异常时。
 *      3、调用stop方法 停止运行  这样容易出现死锁。
 */
public class MyThreadExtendDemo {
    /**   3种创建线程的案例  */
    public static void main(String[] args) throws Exception {
        //1、通过继承Thread 重写run方法 创建线程。
        MyThread myThread = new MyThread();
        myThread.start();

        //2、通过实现Runnable接口 重写run方法  创建线程。
        Thread thread2 = new Thread(new MyRunnable());
        thread2.start();

        //3、FutureTask implements RunnableFuture extends Runnable, Future<V>
        //FutureTask 中有定义一个 Callable接口 的构造方法 所以我们通过实现该接口 创建线程。
        //3.1创建一个FutureTask<T>实例 该泛型要和Callable<T>的泛型类型一致。
        FutureTask<String> futureTask = new FutureTask(new MyCallable());
        //3.2创建Thread对象 构造方法传入 实现了Runnable的FutureTask对象。
        Thread thread = new Thread(futureTask, "线程名MyCallable");
        thread.start();
        //System.out.println(futureTask.cancel(true));  取消执行。
        //System.out.println(futureTask.isCancelled());  判断任务是不是完成。
        //3.3获取线程执行完后的结果 FutureTask因实现了Future 所以通过Futrue中的get可以获取返回结果。
        System.out.println("Callable线程的结果打印：" + futureTask.get());
    }


}
